

Face::Face(void)
{
}

Face::~Face(void)
{
#ifndef BOOST
  Clean();
#endif
}
#include "Face.h"

void Face::Clean()
{
  edgeForIterator it;

  figureEdge * edge;

  for(it = begin();
      it != end();
      it ++)
  {
#ifndef BOOST
    edge = reinterpret_cast<figureEdge *>(*it);
#else
    edge = (*it);
#endif
    delete(edge);
  }
}

void Face::AddEdge(const figureEdge & e)
{
  edgeForIterator it;
  figureEdge *edge;
  
  edge = new figureEdge();
  *edge = e;

  //m_edgeList.
  push_back((long long) edge);
  //push_back(edge);

  if(size() > 1)
  {
    it = --end(); //Now the pointer point to the last insertet element

#ifndef BOOST
    edge->prev = reinterpret_cast<figureEdge *>(*(--it));
    (reinterpret_cast<figureEdge *>(*it))->next = reinterpret_cast<figureEdge *>(edge);

    //We have to connect the end with the begin

    it = begin();

    edge->next = reinterpret_cast<figureEdge *>(*it);
    (reinterpret_cast<figureEdge *>(*it))->prev = edge;
#else
    edge->prev = (--it)->this;
    (--it)->next = edge;

    //We have to connect the end with the begin

    it = begin();

    edge->next = *it;
    it->prev = edge;
#endif
  }

}

void Face::AddEdge(const figureVertice & v1, const figureVertice & v2)
{
  //TODO:
}

Face * Face::Copy()
{
  Face * _face = new Face();
  edgeForIterator it;
  figureEdge *figEdge, * newfig;

  for(it = begin();
      it!= end();
      it++)
  {
#ifndef BOOST
    figEdge = reinterpret_cast<figureEdge *>(*it);
#else
    figEdge = *it;
#endif
    newfig = new figureEdge();
    
    //_face->push_back(new figureEdge(*it));
  }       

  return _face;
}

void Face::Draw(const HWND & hwnd, const POINT & shift)
{
  edgeForIterator it;
  HDC hdc = GetDC(hwnd);
  figureEdge  *figEdge;
  int r,g,b;
  //We have to set a color for Face
  HPEN   newpen,oldpen;
  HBRUSH newbrush,oldbrush;
  
  r = (((double)rand() / (double)(RAND_MAX + 1))) * 255;
  g = (((double)rand() / (double)(RAND_MAX + 1))) * 255;
  b = (((double)rand() / (double)(RAND_MAX + 1))) * 255;
  newpen = CreatePen(PS_SOLID,4,RGB(r,g,b));
  newbrush = CreateSolidBrush(RGB(r,g,b));

  oldpen    = (HPEN) SelectObject(hdc,newpen);
  oldbrush  = (HBRUSH) SelectObject(hdc,newbrush);

  for(it = begin();
      it!= end();
      it++)
  {
    figEdge = reinterpret_cast<figureEdge *>(*it);
    MoveToEx(hdc,figEdge->_begin.x - shift.x ,figEdge->_begin.y - shift.y ,NULL);
    LineTo(hdc,figEdge->_end.x - shift.x ,figEdge->_end.y - shift.y);    
  }      

  SelectObject(hdc,oldpen);
  SelectObject(hdc,oldbrush);

  DeleteObject(newpen);
  DeleteObject(newbrush);
  ReleaseDC(hwnd, hdc);

}


bool Face::GetCirculation()
{
  //We have to find a smallest x-coordinate point 
  //from this point we have to get previous point and next
  //and check if the next point has a smaller coordinates then previous
  //TODO: it returns only current figure, and forgot about previous
  int i = 0;
  Face::iterator it;
  POINT p={2000,0},prev,next,t;

  _ASSERT(size() > 2);
  
  //We have to find a point which has a y coordinate as maximum (sic!)

  if(size() < 4)
  {
    prev = reinterpret_cast<figureEdge *>(front())->_begin;
    p    = reinterpret_cast<figureEdge *>(*(++ begin()))->_begin;
    next = reinterpret_cast<figureEdge *>(back())->_begin;
  }else
  {
    prev = reinterpret_cast<figureEdge *>(back())->_begin;
    p    = reinterpret_cast<figureEdge *>(front())->_begin;
    next = reinterpret_cast<figureEdge *>(*(++begin()))->_begin;
    for(it = ++begin() ;
        it != end();
        it ++)
    {
      t = (reinterpret_cast<figureEdge *>(*it))->_begin;
      if(t.y > p.y)
      {
        //replace next with p
        //and pre with p
        prev = (reinterpret_cast<figureEdge *>(*(--it)))->_begin;
        it++;
        p    = t;
        it++;
        if(it != end())
        {
          next = (reinterpret_cast<figureEdge *>(*it))->_begin;
          it--;
        }else
        {
          next = reinterpret_cast<figureEdge *>(front())->_begin;
        }
        it--;
      }



/*
      i++;
      if(p.x > (reinterpret_cast<figureEdge *>(*it))->_begin.x)
      {
        p = (reinterpret_cast<figureEdge *>(*it))->_begin;
        if(i == 1)
          prev = (reinterpret_cast<figureEdge *>(back()))->_begin;
        else
        {
          it--;
          prev = (reinterpret_cast<figureEdge *>(*it))->_begin;
          it++;
        }
        if(i == size())
          next = (reinterpret_cast<figureEdge *>(front()))->_begin;
        else
        {
          it++;
          next = (reinterpret_cast<figureEdge *>(*it))->_begin;
          it--;
        }
      }
      */
    }
  }
  //if(it != end())
  //p = (reinterpret_cast<figureEdge *>(front()))->_begin;
  //next = (reinterpret_cast<figureEdge *>(*(++ begin())))->_begin;

  POINT3D p1,p2,p3;
  Vector3D va,vb;

  //p1 it is a view point it is a started point for calculation, where z = 1
  //p1.x = (p.x + next.x) / 2;
  //p1.y = (p.y + next.y) / 2;
  p1.x = prev.x;
  p1.y = prev.y;
  p1.z = 1;
  
  p2.x = p.x;
  p2.y = p.y;
  p2.z = 1;

  p3.x = next.x;
  p3.y = next.y;
  p3.z = 1;

  va.SetVector(p1,p2);
  vb.SetVector(p2,p3);

  double product;
  product = va.GetProduct(vb);
  //pr = vb.GetProduct(va);
  
  //Vector2D v1(prev,p),v2(p,next);
  

  //product = v1.GetProduct(v2);
  if(product < 0 )
  {
    //We have wrong circulation
    return false;
  }

  return true;
}


//----------------------------------FACEFACTORY CLASS-------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------------------


faceList FaceFactory::m_faceList;

FaceFactory::FaceFactory()
{
}

FaceFactory::~FaceFactory()
{
}

void FaceFactory::AddFace(Face * face)
{
  m_faceList.push_back(face);
}

void FaceFactory::Test()
{
  faceListIterator it;
  Face *f;

  for(it = m_faceList.begin();
      it != m_faceList.end();
      it++)
  {
    f = &(*it);
  }
}

void FaceFactory::Draw(const HWND & hwnd, const POINT & shift)
{

  //CGTriangulate gt;
  //gt.Draw(hwnd);
  
  faceListIterator it;

  for(it = m_faceList.begin();
      it != m_faceList.end();
      it++)
  {
    Sleep(500);
    it->Draw(hwnd, shift);
  }
}

void FaceFactory::Clean()
{
  m_faceList.clear();
}

bool FaceFactory::SetFirtsEl()
{ 
  if(m_faceList.size() > 0 )
  {
    m_faceIter = m_faceList.begin();
    return true;
  }else
    return false;
}

const Face * FaceFactory::GetNextEl()
{
  if(m_faceIter != m_faceList.end())
    return &(*(m_faceIter++));
  else
    return NULL;
}

bool FaceFactory::GetFirstFace(Face & face)
{
  Face facetmp;
 
  if(m_faceIter != m_faceList.end())
  {
    facetmp = *m_faceIter;
    face = facetmp;
    return true;
  }else
    return false;
}

bool FaceFactory::GetNextFace(Face & face)
{
  Face facetmp;
  m_faceIter++;
  if(m_faceIter != m_faceList.end())
  {
    facetmp = *m_faceIter;
    face = facetmp;
    return true;
  }else
    return false;
}


